/*
 * Copyright 2007 The semap project development team.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Created by dulanov at Nov 16, 2007 6:14:34 AM.
 *
 * $Id: NativeRepository.java 891 2007-12-09 07:56:46Z dulanov $
 */

package net.sf.semap.sandbox.sesame;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;

import net.sf.semap.sandbox.rio.ntriples.NTriplesWriter;
import net.sf.semap.sandbox.sesame.resultio.sparqltsv.SPARQLResultsTSVWriter;

import org.openrdf.query.GraphQueryResult;
import org.openrdf.query.MalformedQueryException;
import org.openrdf.query.QueryEvaluationException;
import org.openrdf.query.QueryLanguage;
import org.openrdf.query.TupleQueryResult;
import org.openrdf.query.TupleQueryResultHandler;
import org.openrdf.query.TupleQueryResultHandlerException;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.sail.SailRepository;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFHandler;
import org.openrdf.rio.RDFHandlerException;
import org.openrdf.rio.RDFParseException;
import org.openrdf.sail.nativerdf.NativeStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author <a href="mailto:dulanov@gmail.com">dulanov</a>
 * @version $Id: NativeRepository.java 891 2007-12-09 07:56:46Z dulanov $
 */
public class NativeRepository {

	private static final Logger logger = LoggerFactory.getLogger(NativeRepository.class);

	private Repository repository;

	public NativeRepository(String repoPathName) throws RepositoryException {
		(repository = new SailRepository(new NativeStore(new File(repoPathName)))).initialize();
	}

	public void populateByDefault() throws RepositoryException, RDFParseException, IOException {
		RepositoryConnection connection = repository.getConnection();
		try {
			if (0 != connection.size()) {
				if (logger.isInfoEnabled()) {
					logger.info("Repository was populated by {} statements already", connection.size());
				}
				return;
			}

			connection.add(new File("./ext/ontology/dc.owl"), "http://purl.org/dc/elements/1.1/", RDFFormat.RDFXML);
			connection.add(new File("./ext/ontology/dcterms.owl"), "http://purl.org/dc/terms/", RDFFormat.RDFXML);
			connection.add(new File("./ext/ontology/foaf.owl"), "http://xmlns.com/foaf/0.1/", RDFFormat.RDFXML);
			connection.add(new File("./ext/ontology/geo.owl"), "http://www.w3.org/2003/01/geo/", RDFFormat.RDFXML);
			connection.add(new File("./ext/ontology/owl.owl"), "http://www.w3.org/2002/07/owl#", RDFFormat.RDFXML);
			connection.add(new File("./ext/ontology/rdf.owl"), "http://www.w3.org/1999/02/22-rdf-syntax-ns#", RDFFormat.RDFXML);
			connection.add(new File("./ext/ontology/rdfs.owl"), "http://www.w3.org/2000/01/rdf-schema#", RDFFormat.RDFXML);
			connection.add(new File("./ext/ontology/vs.owl"), "http://www.w3.org/2003/06/sw-vocab-status/ns#", RDFFormat.RDFXML);
			connection.add(new File("./ext/ontology/wot.owl"), "http://xmlns.com/wot/0.1/", RDFFormat.RDFXML);

			connection.add(new File("./src/main/rdf/specdata.rdf"), "http://localhost/", RDFFormat.RDFXML);

			if (logger.isInfoEnabled()) {
				logger.info("Repository was populated by default successfully");
			}
		} finally {
			connection.close();
		}
	}

	public TupleQueryResult evaluateTupleQuery(QueryLanguage lang, String query) throws QueryEvaluationException, RepositoryException, MalformedQueryException {
		RepositoryConnection connection = repository.getConnection();
		try {
			return connection.prepareTupleQuery(lang, query).evaluate();
		} finally {
			connection.close();
		}
	}

	public void evaluateTupleQuery(QueryLanguage lang, String query, TupleQueryResultHandler handler) throws QueryEvaluationException, TupleQueryResultHandlerException, RepositoryException, MalformedQueryException {
		RepositoryConnection connection = repository.getConnection();
		try {
			connection.prepareTupleQuery(lang, query).evaluate(handler);
		} finally {
			connection.close();
		}
	}

	public boolean evaluateBooleanQuery(QueryLanguage lang, String query) throws QueryEvaluationException, RepositoryException, MalformedQueryException {
		RepositoryConnection connection = repository.getConnection();
		try {
			return connection.prepareBooleanQuery(lang, query).evaluate();
		} finally {
			connection.close();
		}
	}

	public GraphQueryResult evaluateGraphQuery(QueryLanguage lang, String query) throws QueryEvaluationException, RepositoryException, MalformedQueryException {
		RepositoryConnection connection = repository.getConnection();
		try {
			return connection.prepareGraphQuery(lang, query).evaluate();
		} finally {
			connection.close();
		}
	}

	public void evaluateGraphQuery(QueryLanguage lang, String query, RDFHandler handler) throws QueryEvaluationException, RDFHandlerException, RepositoryException, MalformedQueryException {
		RepositoryConnection connection = repository.getConnection();
		try {
			connection.prepareGraphQuery(lang, query).evaluate(handler);
		} finally {
			connection.close();
		}
	}

	public static void main(String[] args) {

		String[] tupleQueries = new String[] {

	        "SELECT ?uri\n"
            + "WHERE\n"
            + "{\n"
            + "?uri <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .\n"
            + "}"

	        ,

	        "SELECT * \n"
            + "WHERE\n"
            + "{\n"
            + "?uri <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .\n"
            + "?uri <http://xmlns.com/foaf/0.1/knows> <http://localhost/contacts/timbl> .\n"
            + "}\n" + "LIMIT 10"

	        ,

	        "SELECT DISTINCT * \n"
            + "WHERE\n"
            + "{\n"
            + "?uri <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .\n"
            + "?uri <http://xmlns.com/foaf/0.1/holdsAccount>\n"
            + "        [<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/OnlineAccount> ;\n"
            + "         <http://xmlns.com/foaf/0.1/accountServiceHomepage> <http://www.skype.com/> ;\n"
            + "         <http://xmlns.com/foaf/0.1/accountName> ?skype_name] .\n"
            + "}"
		};

		String[] booleandQueries = new String[] {

        	"ASK\n"
            + "{\n"
            + "<http://localhost/contacts/timbl> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> ;\n"
            + "                                  <http://xmlns.com/foaf/0.1/gender> \"male\" .\n"
            + "}"
		};

		String[] graphQueries = new String[] {

	        "CONSTRUCT\n"
            + "{\n"
            + "<http://localhost/contacts/timbl> <http://xmlns.com/foaf/0.1/name> ?name_en .\n"
            + "<http://localhost/contacts/timbl> <http://xmlns.com/foaf/0.1/mbox> ?mbox .\n"
            + "<http://localhost/contacts/timbl> <http://xmlns.com/foaf/0.1/homepage> ?homepage .\n"
            + "}\n"
            + "WHERE\n"
            + "{\n"
            + "<http://localhost/contacts/timbl> <http://xmlns.com/foaf/0.1/name> ?name_en . FILTER (isIRI(?name_en) || lang(?name_en) = \"\" || lang(?name_en) = \"en\")\n"
            + "<http://localhost/contacts/timbl> <http://xmlns.com/foaf/0.1/mbox> ?mbox . FILTER (isIRI(?mbox) || lang(?mbox) = \"\" || lang(?mbox) = \"en\")\n"
            + "<http://localhost/contacts/timbl> <http://xmlns.com/foaf/0.1/homepage> ?homepage . FILTER (isIRI(?homepage) || lang(?homepage) = \"\" || lang(?homepage) = \"en\")\n"
            + "}"

	        ,

	        "CONSTRUCT\n"
            + "{\n"
            + "?uri <http://xmlns.com/foaf/0.1/name> ?name .\n"
            + "}\n"
            + "WHERE\n"
            + "{\n"
            + "?uri <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> ;\n"
            + "     <http://xmlns.com/foaf/0.1/name> ?name .\n"
            + "}"
		};

		try {
			NativeRepository repository = new NativeRepository("./target/sesame2/");
			repository.populateByDefault();

			for (String queryString : tupleQueries) {
				StringWriter stringWriter = new StringWriter();
				repository.evaluateTupleQuery(QueryLanguage.SPARQL, queryString, new SPARQLResultsTSVWriter(stringWriter));
				if (logger.isInfoEnabled()) {
					logger.info("sparql query:\n{}\n---\n{}", queryString, stringWriter.getBuffer().toString());
				}
			}

			for (String queryString : booleandQueries) {
				boolean result = repository.evaluateBooleanQuery(QueryLanguage.SPARQL, queryString);
				if (logger.isInfoEnabled()) {
					logger.info("sparql query:\n{}\n---\n{}", queryString, result);
				}
			}

			for (String queryString : graphQueries) {
				StringWriter stringWriter = new StringWriter();
				repository.evaluateGraphQuery(QueryLanguage.SPARQL, queryString, new NTriplesWriter(stringWriter));
				if (logger.isInfoEnabled()) {
					logger.info("sparql query:\n{}\n---\n{}", queryString, stringWriter.getBuffer().toString());
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}
}
